/*
 * @lc app=leetcode.cn id=641 lang=csharp
 *
 * [641] 设计循环双端队列
 */

// @lc code=start
public class MyCircularDeque {

  class Node
  {
    public int Value { get; set; }
    public Node Prev { get; set; }
    public Node Next { get; set; }

    public Node(int val)
    {
      this.Value = val;
    }
  }

  private Node _dummy_front = new Node(-1);
  private Node _dummy_rear = new Node(-1);
  private int _capacity;
  private int _size = 0;

  public MyCircularDeque(int k) {
    this._capacity = k;
    _dummy_front.Next = _dummy_rear;
    _dummy_rear.Prev = _dummy_front;
  }
  
  public bool InsertFront(int value) {
    if (_size == _capacity) {
      return false;
    }
    InsertBetween(_dummy_front, _dummy_front.Next, new Node(value));
    return true;
  }
  
  public bool InsertLast(int value) {
    if (_size == _capacity) {
      return false;
    }
    InsertBetween(_dummy_rear.Prev, _dummy_rear, new Node(value));
    return true;
  }
  
  public bool DeleteFront() {
    if (_size == 0) {
      return false;
    }
    Drop(_dummy_front.Next);
    return true;
  }
  
  public bool DeleteLast() {
    if (_size == 0) {
      return false;
    }
    Drop(_dummy_rear.Prev);
    return true;
  }
  
  public int GetFront() {
    return _size == 0 ? -1 : _dummy_front.Next.Value;
  }
  
  public int GetRear() {
    return _size == 0 ? -1 : _dummy_rear.Prev.Value;
  }
  
  public bool IsEmpty() {
    return _size == 0;
  }
  
  public bool IsFull() {
    return _size == _capacity;
  }

  private void InsertBetween(Node prev, Node next, Node node) {
    node.Prev = prev;
    node.Next = next;

    prev.Next = node;
    next.Prev = node;

    ++_size;
  }

  private void Drop(Node node) {
    node.Next.Prev = node.Prev;
    node.Prev.Next = node.Next;

    node.Next = null;
    node.Prev = null;

    --_size;
  }
}

/**
 * Your MyCircularDeque object will be instantiated and called as such:
 * MyCircularDeque obj = new MyCircularDeque(k);
 * bool param_1 = obj.InsertFront(value);
 * bool param_2 = obj.InsertLast(value);
 * bool param_3 = obj.DeleteFront();
 * bool param_4 = obj.DeleteLast();
 * int param_5 = obj.GetFront();
 * int param_6 = obj.GetRear();
 * bool param_7 = obj.IsEmpty();
 * bool param_8 = obj.IsFull();
 */
// @lc code=end

